//
//  JRHttpRequestManager.swift
//  JRHttpRequestManager
//
//  Created by 京睿 on 2017/4/26.
//  Copyright © 2017年 JingRuiWangKe. All rights reserved.
//

import UIKit
import AFNetworking

extension AFHTTPSessionManager {
    @nonobjc static var JRManager: AFHTTPSessionManager = {
        let url = URL.init(string: kConfig.baseUrl ?? "")
        let manager = AFHTTPSessionManager.init(baseURL: url)
        manager.responseSerializer.acceptableContentTypes = kConfig.acceptableContentTypes
        manager.responseSerializer = kConfig.responseSerializer
        kConfig.headers.forEach {
            manager.requestSerializer.setValue($0.value, forHTTPHeaderField: $0.key)
        }
        manager.requestSerializer.timeoutInterval = kConfig.timeoutInterval
        
        return manager
    } ()
}

public class JRHttpRequestManager: NSObject {
    
    fileprivate var success: (([String: AnyObject]?)->())!
    fileprivate var failure: ((String?)->())!
    fileprivate var encryptionManager = kConfig.encryptionManager
    fileprivate override init() { }
}

extension JRHttpRequestManager {
    private enum RequestType {
        case post, get
    }
    
    @discardableResult
    public convenience init(POST url: String!, params: Any!, header: [String: String] = [:], constructingBody: ((AFMultipartFormData) -> Void)! = nil) {
        self.init()
        
        let manager = AFHTTPSessionManager.JRManager
        kConfig.headers = header
        startRequest(manager, api: url, params: params, type: .post, constructingBody: constructingBody)
    }
    
    @discardableResult
    public convenience init(GET url: String!, params: Any! = nil, header: [String: String] = [:]) {
        self.init()
        let manager = AFHTTPSessionManager.JRManager
        kConfig.headers = header
        startRequest(manager, api: url, params: params, type: .get)
    }
    
    private func startRequest(_ manager: AFHTTPSessionManager, api: String!, params: Any!, type: RequestType = .post, constructingBody: ((AFMultipartFormData) -> Void)! = nil) {
        var params = BaseParameter().addition(params)
        
        if let tmp = encryptionManager.encryptionResult(params) {
            //print(tmp)
            params = tmp
        }
        
        switch type {
        case .post:
            manager.post(api, parameters: params, constructingBodyWith: constructingBody, progress: { (process) in
                
            }, success: { (task, responseObject) in
                self.success(response: responseObject)
            }, failure: { (task, error) in
                self.failure(response: error)
            })
            
        default:
            manager.get(api,
                        parameters: params,
                        progress: { (process) in
                            
            }, success: { (task, responseObject) in
                self.success(response: responseObject)
            }, failure: { (task, error) in
                self.failure(response: error)
            })
        }
    }
    
    /// 收到服务器成功返回#1
    ///
    /// - Parameter response: response description
    private func success(response: Any!) {
        if let response = response as? Data {
            do {
                guard let result = try JSONSerialization.jsonObject(with: response, options: JSONSerialization.ReadingOptions.mutableContainers) as? [String: AnyObject] else {
                    dealWithFailure(by: "返回值非字典")
                    return
                }
                guard let code = result[kConfig.successField] as? NSNumber, code == kConfig.successCode else {
                    guard let desc = result[kConfig.failingDescField] as? String else {
                        dealWithFailure(by: "网络请求失败")
                        return
                    }
                    dealWithFailure(by: desc)
                    return
                }
                dealWithSuccess(by: result)
            } catch {
                dealWithFailure(by: "JSON解析异常")
            }
        } else if let response = response as? [String: AnyObject] {
            guard let code = response[kConfig.successField] as? NSNumber, code == kConfig.successCode else {
                guard let desc = response[kConfig.failingDescField] as? String else {
                    dealWithFailure(by: "网络请求失败")
                    return
                }
                dealWithFailure(by: desc)
                return
            }
            dealWithSuccess(by: response)
        } else {
            dealWithFailure(by: "数据格式解析错误")
        }
    }
    
    /// 收到服务器失败返回#1
    ///
    /// - Parameter response: response description
    private func failure(response: Error!) {
        dealWithFailure(by: response.localizedDescription)
    }
    
    /// 处理成功请求#2
    ///
    /// - Parameter result: 成功返回值
    private func dealWithSuccess(by result: [String: AnyObject]) {
//        print(result)
        success?(result)
    }
    
    /// 处理失败请求#2
    ///
    /// - Parameter des: 失败描述
    private func dealWithFailure(by des: String) {
        failure?(des)
    }
    
    @discardableResult
    public func successful(_ callback: @escaping (([String: AnyObject]?)->())) -> JRHttpRequestManager {
        success = callback
        return self
    }
    
    @discardableResult
    public func failed(_ callback: @escaping ((String?)->())) -> JRHttpRequestManager {
        failure = callback
        return self
    }
}
